package com.atwisdom.star.thirdInterface.business.Impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.common.util.JsonUtil;
import com.atwisdom.star.common.util.UuidTool;
import com.atwisdom.star.common.vo.ActionData;
import com.atwisdom.star.common.vo.JsonResult;
import com.atwisdom.star.common.vo.ResultInfo;
import com.atwisdom.star.common.vo.StatusCode;
import com.atwisdom.star.redis.util.RedisUtil;
import com.atwisdom.star.thirdInterface.business.InfInstanceDslService;
import com.atwisdom.star.thirdInterface.business.InfInstanceHistoryDslService;
import com.atwisdom.star.thirdInterface.business.InterfaceService;
import com.atwisdom.star.thirdInterface.pojo.InfConfig;
import com.atwisdom.star.thirdInterface.service.InfConfigService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.connection.stream.RecordId;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Slf4j
@Service
public class InterfaceServiceImpl implements InterfaceService {

    @Resource
    RedisUtil redisUtil;

    @Resource
    InfInstanceDslService infInstanceDslService;

    @Resource
    InfInstanceHistoryDslService infInstanceHistoryDslService;

    @Resource
    InfConfigService infConfigService;

    /**
     * 实体模型接口转换
     *
     * @return
     */
    @Override
    public ResultInfo<?>  addEntity(JSONObject infObject,HttpServletRequest httpServletRequest) {
        String[] keyList = infObject.keySet().toArray(new String[0]);
        for(String infSysName : keyList) {
            //构造http信息
            JSONObject jsonHttp = new JSONObject();
            jsonHttp.putAll(getHttpHeader(httpServletRequest));
            jsonHttp.putAll(getHttpLine(httpServletRequest));
            //保存第三方接口数据
            boolean result = addInfSysInstance(infSysName, infObject.getJSONObject(infSysName), jsonHttp);
            if (!result) {
                return JsonResult.error(StatusCode.ERROR_INVALID_OPERATION);
            }
        }

        return JsonResult.success();
    }


    /**
     * 找到某一接口配置json
     * @param infConfig
     * @param infName
     * @return
     */
    private JSONObject findInfConfigObj(String infName,JSONObject infConfig){
        Set<String> infCfgNameList = infConfig.keySet();
        for(String infCfgName : infCfgNameList){
            if(infName.equalsIgnoreCase(infCfgName)){
                return infConfig.getJSONObject(infCfgName);
            }
        }
        return null;
    }


    /**
     * 属性转换
     */
    private JSONObject changeProp(JSONObject thirdObject,JSONObject classnameObj){
        JSONObject propObject = new JSONObject();
        Set<String> classnamePropList = classnameObj.keySet();
        for (String classnameProp : classnamePropList) {    //配置转换 "年龄": "people.age",
            String classnameKey = classnameObj.getString(classnameProp);
            Object starEntityValue = getInfData(thirdObject, classnameKey);
            if (starEntityValue != null)
                propObject.put(classnameProp, starEntityValue);
        }
        return propObject;
    }


    /**
     * 转换第三方到本系统
     */
    private JSONObject changeThirdtoStar(String infName,JSONObject thirdEntity,JSONObject infConfig){
        JSONObject starEntity = new JSONObject();
        //具体接口配置表
        JSONObject infConfigObj = findInfConfigObj(infName,infConfig);
        Set<String> classnameList = infConfigObj.keySet();
        for(String classname : classnameList){
            JSONObject classnameObj = infConfigObj.getJSONObject(classname);
            //属性映射
            JSONObject starEntityProp = changeProp(thirdEntity,classnameObj);
            if(starEntityProp.size()==0) continue;
            starEntity.put(classname,starEntityProp);
        }
        return starEntity;
    }


    private String getKeyName(JSONObject node){
        String[] keys = node.keySet().toArray(new String[0]);
        return keys[0];
    }

    /**
     * 数组转换
     * @return
     */
    private JSONObject changeArray(JSONArray starEntityList){
        //找到所有key
        List<String> infNameList = new ArrayList<>();
        for(int i=0;i<starEntityList.size();i++){
            JSONObject node = starEntityList.getJSONObject(i);
            String keyname = getKeyName(node);
            if(!infNameList.contains(keyname)) {
                infNameList.add(keyname);
            }
        }
        //扫描每一个keyname
        JSONObject starEntity = new JSONObject();
        for(String ckeyName : infNameList){
            JSONArray aryStarEntity = new JSONArray();
            for(int i=0;i<starEntityList.size();i++){
                JSONObject node = starEntityList.getJSONObject(i);
                String keyname = getKeyName(node);
                if(ckeyName.equalsIgnoreCase(keyname)){
                    aryStarEntity.add(node.getJSONObject(keyname));
                }
            }
            starEntity.put(ckeyName,aryStarEntity);
        }
        return starEntity;
    }


    /**
     * 去除接口，保留内容
     * @param starEntity
     * @return
     */
    private JSONObject removeInf(JSONObject starEntity){
        JSONObject starEntityFinal = new JSONObject();
        Set<String> infNameList = starEntity.keySet();   //接口列表
        for(String infName : infNameList){
            starEntityFinal.putAll(starEntity.getJSONObject(infName));
        }
        return starEntityFinal;
    }


    /**
     * 保存第三方接口数据
     */
    private boolean addInfSysInstance(String infSysName, JSONObject infSysObject,JSONObject jsonHttp){
        //得到接口-模型配置JSON
        QueryWrapper<InfConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("infSysName", infSysName);
        List<InfConfig> infConfigList = infConfigService.list(queryWrapper);
        if(infConfigList.size() == 0) {
            return false;
        }
        InfConfig infConfig = infConfigList.get(0);
        JSONObject jsonConfig = infConfig.getConfig();


        //三方系统数据infSysObject
        JSONObject starInfEntity = new JSONObject();
        Set<String> infNameList = infSysObject.keySet();   //接口列表
        for(String infName : infNameList){
            //第三方实例列表
            JSONArray starEntityList = new JSONArray();
            //判断是否是数组，如果不是则转成数组
            Object obj = infSysObject.get(infName);
            JSONArray thirdEntityList = null;
            if(obj instanceof Map) {
                thirdEntityList = new JSONArray();
                thirdEntityList.add(infSysObject.getJSONObject(infName));
            }else {
                thirdEntityList = infSysObject.getJSONArray(infName);
            }
            for(int i=0;i<thirdEntityList.size();i++){
                JSONObject thirdEntity = thirdEntityList.getJSONObject(i);
                //转换后的实例
                JSONObject starEntity = changeThirdtoStar(infName,thirdEntity,jsonConfig);
                starEntityList.add(starEntity);
            }
            //数组格式转换
            JSONObject starEntity = changeArray(starEntityList);

            starInfEntity.put(infName,starEntity);
        }
        starInfEntity = removeInf(starInfEntity);


        //保存数据库
        String infInstanceId = UuidTool.getUUID32();
        JSONObject entityData = new JSONObject();
        entityData.put("id",infInstanceId);
        entityData.put("infSysName",infSysName);
        entityData.put("infIns", infSysObject);
        entityData.put("entityIns",starInfEntity);
        entityData.put("protocol",jsonHttp);
        List<JSONObject> entityList = new ArrayList<>();
        entityList.add(entityData);
        ActionData<JSONObject> entityActionData = new ActionData<>();
        entityActionData.setData(entityList);
        infInstanceDslService.add(entityActionData);

        //保存历史表
        JSONObject entityDataHis = new JSONObject();
        entityDataHis.put("infInstanceId",infInstanceId);
        entityDataHis.put("infSysName",infSysName);
        entityDataHis.put("infIns", infSysObject);
        entityDataHis.put("entityIns",starInfEntity);
        entityDataHis.put("protocol",jsonHttp);
        List<JSONObject> entityListHis = new ArrayList<>();
        entityListHis.add(entityDataHis);
        ActionData<JSONObject> entityActionDataHis = new ActionData<>();
        entityActionDataHis.setData(entityListHis);
        infInstanceHistoryDslService.add(entityActionDataHis);

        //通知redis
        String streamName = "atWisdomStream";
        RecordId recordId = redisUtil.addMapMessage(streamName, starInfEntity);
        log.info("recordId:{}",recordId);

        return true;
    }



    private Object getInfData(JSONObject infObject,String infKey){
        String[] path = infKey.split("\\.");
        JSONObject obj = infObject;
        for (int i =0;i<path.length;i++){
            if(obj == null) return null;
            if(i < path.length -1)
                obj = obj.getJSONObject(path[i]);
            else
                return obj.get(path[i]);
        }
        return null;
    }


    /**
     * 实体模型批量接口转换
     * @return
     */
    @Override
    public ResultInfo<?>  addBatchEntity(List<JSONObject> infObjectList) {
        //得到接口-模型配置JSON
//        QueryWrapper<InfConfig> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("className", "人员接口");
//        List<InfConfig> infConfigList = infConfigService.list(queryWrapper);
//        if(infConfigList.size() == 0) {
//            return JsonResult.error(StatusCode.ERROR_INVALID_OPERATION);
//        }
//        InfConfig infConfig = infConfigList.get(0);
//        JSONObject jsonConfig = infConfig.getConfig();
//
//        //属性定义匹配转换
//        List<JSONObject> entityObjectList = new ArrayList<>();
//        for(JSONObject infObject : infObjectList) {
//            JSONObject entityObject = new JSONObject();
//            Set<String> keys = jsonConfig.keySet();
//            for(String key : keys){
//                String infKey = jsonConfig.getString(key);
//                Object entityObj = getInfData(infObject,infKey);
//                if(entityObj != null)
//                    entityObject.put(key,entityObj);
//            }
//            entityObjectList.add(entityObject);
//        }
//
//        //保存数据库
//        List<JSONObject> entityList = new ArrayList<>();
//        for(JSONObject entityObject : entityObjectList) {
//            JSONObject entityData = new JSONObject();
//            entityData.put("instanceId", UuidTool.getUUID32());
//            entityData.put("type", "entity");
//            entityData.put("name", UuidTool.getUUID32());
//            entityData.put("className", "人员接口");
//            entityData.put("values", entityObject);
//            entityList.add(entityData);
//        }
//        ActionData<JSONObject> entityActionData = new ActionData<>();
//        entityActionData.setData(entityList);
//        //entityActionData.setClassName(infConfig.getClassName());
//        ResultInfo<?> resultInfo = entityRuntimeDslService.addBatchInstance(entityActionData);
//
//        return resultInfo;
        return null;
    }


    /**
     * 更新实体模型
     * @param jsonObject
     * @return
     */
    @Override
    public ResultInfo<?> updateEntity(JSONObject jsonObject){
        //得到接口-模型配置JSON
        QueryWrapper<InfConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("className", "人员");
        List<InfConfig> infConfigList = infConfigService.list(queryWrapper);
        if(infConfigList.size() == 0) {
            return JsonResult.error(StatusCode.ERROR_INVALID_OPERATION);
        }
        InfConfig infConfig = infConfigList.get(0);
        JSONObject jsonConfig = infConfig.getConfig();

        //属性定义匹配转换
        JSONObject entityObject = new JSONObject();
        Set<String> keys = jsonObject.keySet();
        for(String key : keys){
            String entityKey = jsonConfig.getString(key);
            Object entityObj = jsonObject.get(key);
            entityObject.put(entityKey,entityObj);
        }

        //保存数据库
        JSONObject entityData = new JSONObject();
        entityData.put("id",entityObject.getLong("id"));
        entityData.put("type","entity");
        entityData.put("name", UuidTool.getUUID32());
        //entityData.put("className",infConfig.getClassName());
        entityData.put("values",entityObject);
        List<JSONObject> entityList = new ArrayList<>();
        entityList.add(entityData);
        ActionData<JSONObject> entityActionData = new ActionData<>();
        entityActionData.setId(entityObject.getLong("id"));
        entityActionData.setData(entityList);
        //entityActionData.setClassName(infConfig.getClassName());
        //ResultInfo<?> resultInfo = entityRuntimeDslService.updateInstance(entityActionData);

        return null;
    }


    /**
     * 更新实体模型
     * @param jsonObjectList
     * @return
     */
    @Override
    public ResultInfo<?> updateBatchEntity(List<JSONObject> jsonObjectList){
        //得到接口-模型配置JSON
        QueryWrapper<InfConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("className", "人员");
        List<InfConfig> infConfigList = infConfigService.list(queryWrapper);
        if(infConfigList.size() == 0) {
            return JsonResult.error(StatusCode.ERROR_INVALID_OPERATION);
        }
        InfConfig infConfig = infConfigList.get(0);
        JSONObject jsonConfig = infConfig.getConfig();

        //属性定义匹配转换
        List<JSONObject> entityObjectList = new ArrayList<>();
        for(JSONObject jsonObject : jsonObjectList) {
            JSONObject entityObject = new JSONObject();
            Set<String> keys = jsonObject.keySet();
            for (String key : keys) {
                String entityKey = jsonConfig.getString(key);
                Object entityObj = jsonObject.get(key);
                entityObject.put(entityKey, entityObj);
            }
            entityObjectList.add(entityObject);
        }

        //保存数据库
        List<JSONObject> entityList = new ArrayList<>();
        for(JSONObject entityObject : entityObjectList) {
            JSONObject entityData = new JSONObject();
            entityData.put("id",entityObject.getString("id"));
            entityData.put("type", "entity");
            entityData.put("name", UuidTool.getUUID32());
            //entityData.put("className", infConfig.getClassName());
            entityData.put("values", entityObject);
            entityList.add(entityData);

            ActionData<JSONObject> entityActionData = new ActionData<>();
            entityActionData.setData(entityList);
            //entityActionData.setClassName(infConfig.getClassName());
            //entityRuntimeDslService.updateInstance(entityActionData);
        }

        return JsonResult.success();
    }


    /**
     * 关系模型接口转换
     *
     * @param jsonObject
     * @return
     */
    @Override
    public JSONObject transformForRelation(JSONObject jsonObject) {
        return null;
    }

    /**
     * 监控模型接口转换
     *
     * @param jsonObject
     * @return
     */
    @Override
    public JSONObject transformForMonitor(JSONObject jsonObject) {
        return null;
    }

    /**
     * 计划模型接口转换
     *
     * @param jsonObject
     * @return
     */
    @Override
    public JSONObject transformForPlanner(JSONObject jsonObject) {
        return null;
    }

    /**
     * 流程模板接口转换
     *
     * @param jsonObject
     * @return
     */
    @Override
    public JSONObject transformForProcess(JSONObject jsonObject) {
        return null;
    }

    /**
     * 审批流程模型接口转换
     *
     * @param jsonObject
     * @return
     */
    @Override
    public JSONObject transformForOaProcess(JSONObject jsonObject) {
        return null;
    }

    /**
     * 工艺路线模板接口转换
     *
     * @param jsonObject
     * @return
     */
    @Override
    public JSONObject transformForRouting(JSONObject jsonObject) {
        return null;
    }

    /**
     * 单线图模板接口转换
     *
     * @param jsonObject
     * @return
     */
    @Override
    public JSONObject transformForSimpleMap(JSONObject jsonObject) {
        return null;
    }

    /**
     * 可视化模型接口转换
     *
     * @param jsonObject
     * @return
     */
    @Override
    public JSONObject transformForBi(JSONObject jsonObject) {
        return null;
    }

    /**
     * 统计模型接口转换
     *
     * @param jsonObject
     * @return
     */
    @Override
    public JSONObject transformForStatistics(JSONObject jsonObject) {
        return null;
    }

    /**
     * 统计模板模型接口转换
     *
     * @param jsonObject
     * @return
     */
    @Override
    public JSONObject transformForStatisticsTemplate(JSONObject jsonObject) {
        return null;
    }

    private JSONObject getHttpHeader(HttpServletRequest request) {
        JSONObject header = new JSONObject();
        //获取请求头信息
        Enumeration headerNames = request.getHeaderNames();
        //使用循环遍历请求头，并通过getHeader()方法获取一个指定名称的头字段
        while (headerNames.hasMoreElements()){
            String headerName = (String) headerNames.nextElement();
            header.put(headerName,request.getHeader(headerName));
        }
        return header;
    }

    private JSONObject getHttpLine(HttpServletRequest request){
        JSONObject line = new JSONObject();
        //获取请求行的相关信息
        line.put("method",request.getMethod());
        line.put("queryString",request.getQueryString());
        line.put("protocol",request.getProtocol());
        line.put("contextPath",request.getContextPath());
        line.put("pathInfo",request.getPathInfo());
        line.put("gpathTranslated",request.getPathTranslated());
        line.put("servletPath",request.getServletPath());
        line.put("remoteAddr",request.getRemoteAddr());
        line.put("remoteHost",request.getRemoteHost());
        line.put("remotePort",request.getRemotePort());
        line.put("localAddr",request.getLocalAddr());
        line.put("localName",request.getLocalName());
        line.put("localPort",request.getLocalPort());
        line.put("serverName",request.getServerName());
        line.put("serverPort",request.getServerPort());
        line.put("scheme",request.getScheme());
        line.put("requestURL",request.getRequestURL());

        return line;
    }

}


//        JSONObject jsonConfig = new JSONObject();
//        jsonConfig.put("className","人员");
//        jsonConfig.put("name","姓名");
//        jsonConfig.put("sex","性别");
//        jsonConfig.put("age","年龄");
//        jsonConfig.put("department","所属部门");

//        jsonConfig.put("name","s0");
//        jsonConfig.put("sex","s1");
//        jsonConfig.put("age","s2");
//        jsonConfig.put("department","s3");

//获取模型结构
//        ActionData<JSONObject> actionData = new ActionData<>();
//        actionData.setClassName(jsonConfig.getString("className"));
//        ResultInfo<?> model = entityConfigurationDslService.queryModelByClassName(actionData);
//        JSONObject modelStruct =  (JSONObject)model.getData();


    //接口列表
//    JSONObject entityInfOjbect = new JSONObject();
//    Set<String> infList = jsonConfig.keySet();
//        for(String inf : infList){     //inf   inf1
//                JSONArray entityArray = new JSONArray();
//                JSONArray infArray = infSysObject.getJSONArray(inf);
//                for(int i =0; i< infArray.size(); i++) {
//        //接口数据
//        JSONObject infObject = infArray.getJSONObject(i);
//
//        //配置类
//        JSONObject entityObject = new JSONObject();
//        JSONObject className = jsonConfig.getJSONObject(inf);
//        Set<String> keys = className.keySet();
//        for (String key : keys) {     //key 人员接口
//        //属性定义匹配转换
//        JSONObject confObj = className.getJSONObject(key);
//        JSONObject propObject = new JSONObject();
//        Set<String> confList = confObj.keySet();
//        for (String conf : confList) {    //配置转换 "年龄": "people.age",
//        String infKey = confObj.getString(conf);
//        Object entityObj = getInfData(infObject, infKey);
//        if (entityObj != null)
//        propObject.put(conf, entityObj);
//        }
//        entityObject.put(key, propObject);
//        }
//        entityArray.add(entityObject);
//        }
//        entityInfOjbect.put(inf,entityArray);
//        }